home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-07-17 | 59.5 KB | 2,053 lines |
- ********************************************************************************
- ** **
- ** Name : 8n1_060.s **
- ** Copyright : © Copyright 96-97 **
- ** Author : Iain Barclay **
- ** Created : 15 Jul 97 **
- ** Version : 43.3 **
- ** **
- ********************************************************************************
- ;
- ; SNMA specific options
- ;
- IFD SNMA
- ;
- CPU M68060
- ;
- SNMAOPT Q,A,M,T,E-,P,R,B
- ;
- ELSE
- ; I have phxopts define this symbol
- IFD PHXASS
- machine 68060
- FPU
- ENDC
- ENDC
- ;
- ;
- NEWCODE SET 1
- SETDSR SET 0
- NCOMM SET 0
- FASTVBR SET 1
- DANGER SET 0
- NEGCHECK SET 1
- EOFCODE SET 1
- ;
- ;
- ;
- SECTION text,CODE
- ;
- ;
- ;
- DEVICES_SERIAL_I_OBSOLETE EQU 1
- ;
- ;
- ;
- INCLUDE "exec/lists.i"
- INCLUDE "exec/memory.i"
- INCLUDE "exec/resident.i"
- INCLUDE "exec/devices.i"
- INCLUDE "exec/execbase.i"
- INCLUDE "exec/io.i"
- INCLUDE "exec/ports.i"
- INCLUDE "exec/errors.i"
- INCLUDE "exec/initializers.i"
- INCLUDE "intuition/preferences.i"
- INCLUDE "devices/timer.i"
- INCLUDE "devices/serial.i"
- INCLUDE "hardware/custom.i"
- INCLUDE "hardware/cia.i"
- INCLUDE "hardware/intbits.i"
- INCLUDE "hardware/adkbits.i"
- INCLUDE "resources/misc.i"
- INCLUDE "exec/alerts.i"
- INCLUDE "exec/macros.i"
- INCLUDE "8n1.device_rev.i"
- ;
- ; Define hardware references
- ;
- XREF _custom
- XREF _intena,_intenar,_intreq,_intreqr
- XREF _ciab,_ciabpra
- XREF _serper,_serdat,_serdatr
- XREF _adkcon,_adkconr
- ;
- ; Exec Functions
- ;
- XREF _LVORemDevice,_LVOOpenDevice,_LVOCloseDevice
- XREF _LVOSupervisor
- XREF _LVOAllocMem,_LVOFreeMem,_LVOCopyMem,_LVOTypeOfMem
- XREF _LVOReplyMsg
- XREF _LVOSendIO,_LVOAbortIO
- XREF _LVODisable,_LVOEnable
- XREF _LVOFindName
- XREF _LVOOpenResource
- XREF _LVOAddIntServer,_LVORemIntServer
- XREF _LVOAlert
- XREF _LVOOpenLibrary,_LVOCloseLibrary
- XREF _LVOCacheClearU
- ;
- ; Misc Resource Functions
- ;
- XREF _LVOAllocMiscResource,_LVOFreeMiscResource
- ;
- ; Intuition Functions
- ;
- XREF _LVOGetPrefs
- ;
- ; Mask used to get rid of the printer bits.
- ;
- PRTMASK EQU (CIAF_PRTRPOUT|CIAF_PRTRBUSY)
- ;
- ; Autovector offsets
- ;
- LVL1VEC EQU (1-1)*4+$64
- LVL5VEC EQU (5-1)*4+$64
- VBR_SIZE EQU $400
- custom EQU $dff000
- ciab EQU $bfd000
- ;
- ; New Style device stuff (not the best way but it will have too do for now)
- ; If u don't have New Style stuff defined elsewhere remove these ;
- ;NSCMD_DEVICEQUERY EQU $4000
- ; STRUCTURE NSDEVICEQUERYRESULT,0
- ; ULONG DEVQUERYFORMAT
- ; ULONG SIZEAVAILABLE
- ; UWORD DEVICETYPE
- ; UWORD DEVICESUBTYPE
- ; APTR SUPPORTEDCOMMANDS
- ; LABEL NSDEVICEQUERYRESULT_SIZE
- ;NSDEVTYPE_SERIAL EQU 11
- ;
- ; Device base
- ; pad to longword
- ;
- STRUCTURE Base8n1,LIB_SIZE
- UBYTE vb_pad1
- UBYTE vb_pad2
- ULONG vb_SaveDDRA
- ULONG vb_SavePRA
- APTR vb_MiscBase
- APTR vb_OldLevel1
- APTR vb_OldLevel5
- ULONG vb_SegList
- ULONG vb_DefBaud
- ULONG vb_DefRBufLen
- ULONG vb_CurRBuf
- ULONG vb_CurRBufLen
- ULONG vb_CurBaud
- ULONG vb_SerFlags
- ULONG vb_Initialized
- LABEL sizeof_Base8n1
- ;
- ;
- ;
- ;
- ;
- ;
- Start:
- moveq #-1,d0 ; set return code
- rts ; return
- ;
- ; RamLib looks for this romtag
- ;
- ROMTag DC.W RTC_MATCHWORD ; RT_MATCHWORD
- DC.L ROMTag ; RT_MATCHTAG
- DC.L ENDTag ; RT_ENDSKIP
- DC.B RTF_AUTOINIT ; RT_FLAGS
- DC.B VERSION ; RT_VERSION
- DC.B NT_DEVICE ; RT_TYPE
- DC.B 0 ; RT_PRI
- DC.L Name ; RT_NAME
- DC.L IdString ; RT_IDSTRING
- DC.L Init ; RT_INIT
- ;
- ; Perform device initialization
- ;
- cnop 0,4 ; align for 020+
- InitRoutine:
- exg d0,a0 ; swap seglist and base
- move.l d0,vb_SegList(a0) ; store seglist in base
- move.l a6,SysBase ; store in global storage
- exg a0,d0 ; swap them back
- rts ; return
- ;
- ;
- ;
- cnop 0,4 ; align for 020+
- dev_Open: ; (a1 iorequest, a5 will be Base8n1, a6 sysbase )
- addq.w #1,LIB_OPENCNT(a6) ; fake open so device is not expunged
- move.l a5,-(sp) ; save registers
- move.l a6,a5 ; save base
- ;
- cmpi.w #IOEXTSER_SIZE,MN_LENGTH(a1) ; IORequest size >= IOEXTSER_SIZE
- bcs 50$ ; nope, finish
- ;
- tst.l d0 ; unit 0 specified?
- bne 50$ ; nope, error (who cares?)
- ;
- cmpi.w #1,LIB_OPENCNT(a5) ; currently open?
- bne 10$ ; yep, go process
- ; IOExtSer
- move.l IO_READLEN(a1),vb_SerFlags(a5) ; save flags
- ;
- tst.l vb_Initialized(a5) ; already initialized?
- bne 40$ ; yep, skip initialization
- ;
- movea.l SysBase(pc),a6 ; get ExecBase
- move.l a1,-(sp) ; save register
- ;
- lea miscresource(pc),a1 ; ptr to resource name
- jsr _LVOOpenResource(a6) ; go open it
- move.l d0,vb_MiscBase(a5) ; save base
- ;
- moveq #MR_SERIALPORT,d0 ; set unit number
- bsr allocResource ; go allocate it
- tst.l d0 ; did we get it?
- bne.b 20$ ; nope, error
- ;
- moveq #MR_SERIALBITS,d0 ; set unit number
- bsr allocResource ; go allocate it
- tst.l d0 ; did we get it?
- bne.b 5$ ; nope, error
- ;
- ; Get system preferences
- ;
- lea intuitlib(pc),a1 ; ptr to library name
- moveq #0,d0 ; can't use OldOpenLibrary as this will not be supported.
- jsr _LVOOpenLibrary(a6) ; go open it (any version)
- movea.l d0,a6 ; get intuition base
- ;
- move.l #(pf_SerParShk+3)&$fffffffc,d0 ; size we need (aligned)
- suba.l d0,sp ; reserve space
- ;
- movea.l sp,a0 ; set data area ptr
- jsr _LVOGetPrefs(a6) ; get preferences
- ;
- movea.l a6,a1 ; get intuition base
- movea.l SysBase(pc),a6 ; restore ExecBase
- jsr _LVOCloseLibrary(a6) ; close it
- ;
- moveq #$0f,d0 ; set mask
- and.b pf_SerStopBuf(sp),d0 ; get bufsize index
- moveq #0,d1 ; clear upper half
- addq.l #8,d0 ; calc shift value
- move.w pf_BaudRate(sp),d1 ; get baud rate
- lsl.l #2,d0 ; get default bufsize
- move.l d0,vb_DefRBufLen(a5) ; and store
- IFNE NEWCODE
- move.l .baudTable(pc,d1.l*4),d1 ; get baud rate
- ELSE
- move.w .baudTable(pc,d1.l*2),d1 ; get baud rate
- ENDC
- ;
- move.l d1,vb_DefBaud(a5) ; and store
- ;
- bsr internalReset ; go init baud and buffer
- ;
- lea (pf_SerParShk+3)&$fffffffc(sp),sp ; restore stack
- tst.l d0 ; got 'em?
- beq.b 30$ ; yep, branch
- ;
- moveq #MR_SERIALBITS,d0 ; set unit
- movea.l vb_MiscBase(a5),a6 ; get MiscBase
- jsr _LVOFreeMiscResource(a6) ; release the resource
- ;
- 5$ moveq #MR_SERIALPORT,d0 ; set unit
- movea.l vb_MiscBase(a5),a6 ; get MiscBase
- jsr _LVOFreeMiscResource(a6) ; release the resource
- ;
- 20$ moveq #SerErr_DevBusy,d0 ; set error status
- move.l (sp)+,a1 ; restore registers
- bra 50$ ; go return
- ;
- ; Preferences baud lookup table
- ;
- cnop 0,4 ; align for 020+
- IFNE NEWCODE
- .baudTable:
- dc.l 112,300,1200,2400,4800,9600,19200,31250,38400,57600,62400,64800
- dc.l 76800,115200
- ELSE
- .baudTable:
- dc.w 112,300,1200,2400,4800,9600,19200,31250,38400,57600,62400,64800
- ENDC
- ;
- cnop 0,4 ; align for 020+
- 30$ moveq #0,d1 ; clear flags
- lea timerReq(pc),a1 ; ptr to timer request
- moveq #UNIT_VBLANK,d0 ; set unit
- lea timerdevice(pc),a0 ; ptr to device name
- jsr _LVOOpenDevice(a6) ; go open it
- ;
- IFNE DANGER
- move.w #$04000,_intena
- addq.b #1,IDNestCnt(a6) ; disable interrupts
- ELSE
- jsr _LVODisable(a6) ; disable interrupts
- ENDC
- ;
- move.l #ciab,a1 ; get ptr to ciab
- move.b ciaddra(a1),d0
- move.l d0,vb_SaveDDRA(a5) ; save DDR value
- andi.b #PRTMASK,d0 ; make serial bits input
- move.b (a1),d1 ; ciapra(a1)
- ori.b #CIAF_COMDTR|CIAF_COMRTS,d0 ; make DTR/RTS output
- move.l d1,vb_SavePRA(a5) ; save PR value
- andi.b #CIAF_COMDTR|CIAF_COMRTS|PRTMASK,d0 ; turn on DTR/RTS
- move.b d0,ciaddra(a1)
- andi.b #CIAF_COMCTS|CIAF_COMDSR|PRTMASK,d1 ; make CTS/DSR input
- move.b d1,(a1) ; ciapra(a1)
- ;
- moveq #INTB_PORTS,d0 ; get interrupt number
- lea VBInterrupt(pc),a1 ; get interrupt ptr
- jsr _LVOAddIntServer(a6) ; add it to the list
- ;
- bsr getVBR ; get vector base (in A0)
- ;
- IFNE FASTVBR
- movem.l a0/a5,-(sp) ; save a5, VBR
- move.l a0,a1
- jsr _LVOTypeOfMem(a6)
- btst #MEMB_FAST,d0 ; VBR in fast?
- bne.b nofast$ ; yep, branch
- move.l #VBR_SIZE,d0
- moveq #MEMF_PUBLIC|MEMF_FAST,d1
- jsr _LVOAllocMem(a6) ; Alloc fast-ram for VBR
- tst.l d0
- beq.b nofast$ ; no fast, branch
- move.l (sp),a0 ; get VBR
- move.l d0,a1
- move.l d0,-(sp) ; save new VBR
- move.l #VBR_SIZE,d0
- jsr _LVOCopyMem(a6)
- move.l (sp)+,a0 ; get new VBR
- lea setVBR$(pc),a5
- jsr _LVOSupervisor(a6) ; set new VBR
- jsr _LVOCacheClearU(a6) ; clear cache
- move.l (sp)+,d0 ; was old VBR zero?
- beq.b waszero$ ; yep, branch (don't free)
- move.l d0,a1
- move.l #VBR_SIZE,d0
- jsr _LVOFreeMem(a6)
- waszero$
- bsr getVBR
- bra.b vbend$
- cnop 0,4
- setVBR$
- movec a0,vbr ; set VBR
- rte
- cnop 0,4
- nofast$
- move.l (sp)+,a0 ; restore VBR
- vbend$
- move.l (sp)+,a5 ; restore a5
- ENDC
- move.l LVL1VEC(a0),vb_OldLevel1(a5) ; save original vector
- lea level1(pc),a1 ; get new vector ptr
- move.l a1,LVL1VEC(a0) ; set new vector
- ;
- move.l LVL5VEC(a0),vb_OldLevel5(a5) ; save original vector
- lea level5(pc),a1 ; get new vector ptr
- move.l a1,LVL5VEC(a0) ; set new vector
- ;
- move.l #custom+intena,a1 ; get ptr to custom chips
- move.w #INTF_RBF|INTF_TBE,intreq-intena(a1); clear pending interrupts
- move.w #INTF_SETCLR|INTF_RBF|INTF_TBE,(a1) ; enable RBF & TBE
- ;
- addq.l #1,vb_Initialized(a5) ; set flag
- ;
- IFNE DANGER
- subq.b #1,IDNestCnt(a6)
- bge.b enable$
- move.w #$0C000,(a1)
- enable$
- ELSE
- jsr _LVOEnable(a6) ; enable interrupts
- ENDC
- ;
- move.l (sp)+,a1 ; restore register
- ;
- bra.b 40$ ; go exit
- ;
- cnop 0,4 ; align for 020+
- 10$ moveq #SerErr_DevBusy,d0 ; preset error status
- btst #SERB_SHARED,vb_SerFlags+3(a5) ; opened shared?
- beq.b 50$ ; nope, error
- btst #SERB_SHARED,IO_SERFLAGS(a1) ; requesting shared?
- beq.b 50$ ; nope, error
- ;
- ; Initialize I/O request
- ;
- 40$
- moveq #8,d0 ; get char size
- move.b d0,IO_READLEN(a1) ; set read length
- move.b d0,IO_WRITELEN(a1) ; set write length
- moveq #1,d0 ; get stop bits
- move.b d0,IO_STOPBITS(a1) ; set stop bits
- move.b IO_SERFLAGS(a1),d0
- ori.b #SERF_XDISABLED|SERF_RAD_BOOGIE|SERF_QUEUEDBRK|SERF_7WIRE,d0 ;flags
- andi.b #~(SERF_PARTY_ODD|SERF_PARTY_ON),d0 ; not used
- move.b d0,IO_SERFLAGS(a1)
- move.l vb_CurBaud(a5),IO_BAUD(a1) ; set baud
- moveq #0,d0 ; no error
- move.l vb_CurRBufLen(a5),IO_RBUFLEN(a1) ; set read buffer length
- ;
- addq.w #1,LIB_OPENCNT(a5) ; incr open count
- andi.b #~(1<<LIBB_DELEXP),LIB_FLAGS(a5) ; clear expunge bit
- ;
- 50$ move.b d0,IO_ERROR(a1) ; store error code
- movea.l a5,a6 ; restore base
- move.l (sp)+,a5 ; restore registers
- subq.w #1,LIB_OPENCNT(a6) ; remove fake open
- rts ; return
- ;
- ; Attempt to allocate one of the serial resources.
- ;
- cnop 0,4 ; align for 020+
- allocResource:
- movem.l d0/a6,-(sp)
- lea Name(pc),a1 ; get lock name
- move.l vb_MiscBase(a5),a6 ; get MiscBase
- jsr _LVOAllocMiscResource(a6) ; go allocate it
- tst.l d0 ; did we get it?
- beq.b 20$ ; yep, branch
- ;
- ; It's in use, so we try to locate the device using the string
- ; returned and attempt to remove it.
- ;
- movea.l SysBase(pc),a6 ; get ExecBase
- ;
- movea.l d0,a1 ; get ptr to serial name
- lea DeviceList(a6),a0 ; get ptr to device list
- jsr _LVOFindName(a6) ; go find it
- tst.l d0 ; found?
- beq.b 10$ ; nope, branch
- ;
- movea.l d0,a1 ; xfer device ptr
- jsr _LVORemDevice(a6) ; remove it
- ;
- ; We then retry the allocate.
- ;
- 10$ move.l (sp),d0 ; get unit
- lea Name(pc),a1 ; get lock name
- movea.l vb_MiscBase(a5),a6 ; get MiscBase
- jsr _LVOAllocMiscResource(a6) ; go allocate it
- ;
- 20$ addq.l #4,sp ; restore stack ptr
- move.l (sp)+,a6 ; restore base ptr
- rts ; return
- cnop 0,4 ; align for 020+
- ;
- ; Set exception vectors
- ;
- cnop 0,4 ; align for 020+
- getVBR:
- move.l a5,-(sp) ; save registers
- lea 10$(pc),a5 ; ptr to routine
- jsr _LVOSupervisor(a6) ; get into supervisor state
- move.l (sp)+,a5 ; restore register
- rts ; return
- cnop 0,4
- 10$ movec.l vbr,a0 ; get vector base
- rte ; return
- ;
- ; Device Close routine
- ;
- cnop 0,4 ; align for 020+
- dev_Close:
- ;
- moveq #-1,d0 ; invalidate
- move.l d0,IO_DEVICE(a1) ; device
- ;
- tst.w LIB_OPENCNT(a6) ; check we are open
- beq.b 5$ ; nope, branch
- subq.w #1,LIB_OPENCNT(a6) ; decr open count
- bne dev_Null ; still open? yep, branch
- 5$
- ;
- movem.l a1/a5,-(sp) ; save registers
- ;
- movea.l a6,a5 ; save base
- movea.l SysBase(pc),a6 ; get ExecBase
- ;
- bsr.b getVBR ; get vector base (in A0)
- ;
- moveq #1,d0 ; set not restored code
- ;
- lea level1(pc),a1 ; get our vector ptr
- cmpa.l LVL1VEC(a0),a1 ; do they match?
- bne 10$ ; nope, can't restore
- ;
- lea level5(pc),a1 ; get our vector ptr
- cmpa.l LVL5VEC(a0),a1 ; do they match?
- bne 10$ ; nope, can't restore
- ;
- IFNE DANGER
- move.w #$04000,_intena
- addq.b #1,IDNestCnt(a6) ; disable interrupts
- ELSE
- jsr _LVODisable(a6) ; disable interrupts
- ENDC
- ;
- move.l vb_OldLevel1(a5),LVL1VEC(a0) ; restore original vector
- move.l vb_OldLevel5(a5),LVL5VEC(a0) ; restore original vector
- ;
- moveq #INTB_PORTS,d0 ; get interrupt number
- lea VBInterrupt(pc),a1 ; get interrupt ptr
- jsr _LVORemIntServer(a6) ; remove it from the list
- ;
- move.l #custom+intena,a0 ; get custom base
- move.w #INTF_RBF|INTF_TBE,d0 ; indicate serial interrupts
- move.w d0,(a0) ; disable interrupts
- move.w d0,intreq-intena(a0) ; clear pending interrupts
- ;
- bsr freeBuf ; free allocated buffers
- ;
- move.l #ciab,a0 ; get pointer to ciab
- move.b ciaddra(a0),d0 ; get DDR value
- andi.b #PRTMASK,d0 ; save printer bits
- ori.b #~PRTMASK,d0 ; set serial bits to output
- move.b d0,ciaddra(a0) ; store value
- ;
- move.b (a0),d0 ; get PR value ( ciapra(a0) )
- andi.b #PRTMASK,d0 ; mask out serial bits
- move.l vb_SavePRA(a5),d1 ; get saved value
- andi.b #~PRTMASK,d1 ; mask out printer bits
- or.b d1,d0 ; combine the two
- move.b d0,(a0) ; and store ( ciapra(a0) )
- ;
- move.b ciaddra(a0),d0 ; get DDR value
- andi.b #PRTMASK,d0 ; mask out serial bits
- move.l vb_SaveDDRA(a5),d1 ; get saved value
- andi.b #~PRTMASK,d1 ; mask out printer bits
- or.b d1,d0 ; combine the two
- move.b d0,ciaddra(a0) ; and store
- ;
- lea timerReq(pc),a1 ; get ptr to timer request
- jsr _LVOCloseDevice(a6) ; go close it
- ;
- movea.l vb_MiscBase(a5),a6 ; get MiscBase
- moveq #MR_SERIALBITS,d0 ; set unit
- jsr _LVOFreeMiscResource(a6) ; release the resource
- ;
- moveq #MR_SERIALPORT,d0 ; set unit
- jsr _LVOFreeMiscResource(a6) ; release the resource
- movea.l SysBase(pc),a6 ; restore ExecBase
- ;
- IFNE DANGER
- subq.b #1,IDNestCnt(a6)
- bge.b enable$
- move.w #$0C000,_intena
- enable$
- ELSE
- jsr _LVOEnable(a6) ; enable interrupts
- ENDC
- ;
- subq.l #1,vb_Initialized(a5) ; clear flag
- moveq #0,d0 ; free up everything
- ;
- 10$
- movea.l a5,a6 ; restore base
- ;
- movem.l (sp)+,a1/a5 ; restore registers
- ;
- tst.l d0 ; freed?
- bne.b dev_Null ; nope, can't expunge, exit
- ;
- clr.l vb_SerFlags(a6) ; clear flags
- ;
- btst #LIBB_DELEXP,LIB_FLAGS(a6)
- beq.b dev_Null
- ;
- ; Device Expunge routine (also fall through from dev_Close)
- ;
- dev_Expunge:
- ori.b #1<<LIBB_DELEXP,LIB_FLAGS(a6) ; Set expunge flag
- tst.w LIB_OPENCNT(a6) ; currently open?
- bne.b dev_Null ; yep, so just exit
- ;
- move.l vb_SegList(a6),d0 ; get seglist ptr
- ;
- movea.l a6,a1 ; get base
- ; This is the REMOVE macro
- move.l (a1)+,a0
- move.l (a1),a1 ; LN_PRED
- move.l a0,(a1)
- move.l a1,LN_PRED(a0)
- ;
- movea.l a6,a1 ; get base
- movem.l d0/a6,-(sp) ; save registers (save D0!)
- moveq #0,d0 ; clear work
- move.w LIB_NEGSIZE(a6),d0 ; calculate
- suba.l d0,a1 ; memory address
- add.w LIB_POSSIZE(a6),d0 ; and size
- movea.l SysBase(pc),a6 ; get ExecBase
- jsr _LVOFreeMem(a6) ; free it
- ;
- movem.l (sp)+,d0/a6
- rts ; return (seglist in D0!)
- ;
- ; Device "ExtFunc" routine
- ;
- cnop 0,4 ; align for 020+
- dev_Null:
- moveq #0,d0 ; set return code
- rts ; return
- ;
- ;
- ;
- ;
- cnop 0,4 ; align for 020+
- cmdTable dc.l cmd_Invalid-cmdTable ; CMD_INVALID
- dc.l cmd_Reset-cmdTable ; CMD_RESET
- dc.l cmd_Read-cmdTable ; CMD_READ
- dc.l cmd_Write-cmdTable ; CMD_WRITE
- dc.l cmd_Invalid-cmdTable ; CMD_UPDATE
- dc.l cmd_Clear-cmdTable ; CMD_CLEAR
- dc.l cmd_Invalid-cmdTable ; CMD_STOP
- dc.l cmd_Invalid-cmdTable ; CMD_START
- dc.l cmd_Flush-cmdTable ; CMD_FLUSH
- dc.l sdcmd_Query-cmdTable ; SDCMD_QUERY (CMD_NONSTD)
- dc.l sdcmd_Break-cmdTable ; SDCMD_BREAK
- dc.l sdcmd_SetParams-cmdTable ; SDCMD_SETPARAMS
- endTable
- dc.l nscmd_DeviceQuery-cmdTable ; NSCMD_DEVICEQUERY
- nsendTable
- ;
- ; Device BeginIO routine
- ;
- cnop 0,4 ; align for 020+
- dev_BeginIO:
- move.l a5,-(sp) ; save register
- move.l a6,a5 ; save base
- move.l SysBase(pc),a6 ; get ExecBase
- ;
- move.b #NT_MESSAGE,LN_TYPE(a1) ; set type
- clr.b IO_ERROR(a1) ; clear error
- ;
- andi.b #~(IOSERF_QUEUED|IOSERF_ACTIVE),IO_FLAGS(a1) ; clear flags
- ;
- moveq #0,d0
- move.w IO_COMMAND(a1),d0 ; get command
- lsl.l #2,d0 ; multiply by 4
- moveq #endTable-cmdTable,d1
- cmp.l d1,d0 ; in range?
- bcs.b 5$ ; yip, branch
- cmpi.l #(4*NSCMD_DEVICEQUERY),d0
- bne.b 30$
- move.l d1,d0
- ;
- 5$ move.l cmdTable(pc,d0.l),d0 ; get routine offset
- jsr cmdTable(pc,d0.l) ; go do it
- tst.l d0 ; I/O completed?
- bne.b 19$ ; nope, go return
- ;
- 10$
- btst #IOB_QUICK,IO_FLAGS(a1) ; need to reply?
- bne.b 20$ ; nope, branch
- 15$ jsr _LVOReplyMsg(a6) ; send it back
- ;
- 19$ andi.b #~(1<<IOB_QUICK),IO_FLAGS(a1) ; clear quick bit
- 20$ move.l a5,a6 ; restore base
- move.l (sp)+,a5 ; restore register
- rts ; return
- cnop 0,4 ; align for 020+
- ;
- 30$ move.b #IOERR_NOCMD,IO_ERROR(a1) ; invalid command
- bra.b 10$ ; branch
- ;
- ; Device AbortIO routine
- ;
- cnop 0,4 ; align for 020+
- dev_AbortIO:
- move.l a5,-(sp) ; save registers
- movea.l a6,a5 ; save base
- movea.l SysBase(pc),a6 ; get ExecBase
- ;
- IFNE DANGER
- move.w #$04000,_intena
- addq.b #1,IDNestCnt(a6) ; disable interrupts
- ELSE
- jsr _LVODisable(a6) ; disable interrupts
- ENDC
- ;
- move.l IO_COMMAND(a1),d1 ; get flags
- btst #IOSERB_QUEUED+8,d1 ; queued request?
- bne.b 40$ ; yep, branch
- ;
- btst #IOSERB_ACTIVE+8,d1 ; active request?
- beq.b 10$ ; nope, just exit
- ;
- move.l d1,d0 ; get command
- swap d0
- subq.w #CMD_READ,d0 ; was it a read?
- beq.b 20$ ; yep, go process
- ;
- subq.w #CMD_WRITE-CMD_READ,d0 ; was it a write?
- beq.b 30$ ; yep, go process
- ;
- subq.w #SDCMD_BREAK-CMD_WRITE,d0 ; was it a break?
- beq.b 30$ ; yep, go process
- ;
- ; Fall through or enter from below
- ;
- IFNE DANGER
- 10$ subq.b #1,IDNestCnt(a6)
- bge.b enable$
- move.w #$0C000,_intena
- enable$
- ELSE
- 10$ jsr _LVOEnable(a6) ; enable ints and return
- ENDC
- move.l a5,a6 ; restore base
- move.l (sp)+,a5 ; restore registers
- rts ; return
- ;
- ; Abort an active read request
- ;
- 20$ clr.l cr_IOReq ; no longer active
- bra.b 50$ ; go set flags
- ;
- ; Abort an active write request
- ;
- cnop 0,4 ; align for 020+
- 30$ clr.l cw_Length ; no longer active
- clr.l cw_IOReq ; no longer active
- move.l cw_Buffer(pc),d0 ; get buffer ptr
- sub.l IO_DATA(a1),d0 ; calc number of bytes xfer'd
- move.l d0,IO_ACTUAL(a1) ; store
- ;
- ; Force a TBE interrupt to get the next write going.
- ;
- move.w #INTF_SETCLR|INTF_TBE,_intreq ; make TBE pending
- bra.b 50$ ; go set flags
- ;
- ; Remove I/O from queue.
- ;
- cnop 0,4 ; align for 020+
- 40$ move.l a1,-(sp) ; save ptr
- ; This is the REMOVE macro
- move.l (a1)+,a0
- move.l (a1),a1 ; LN_PRED
- move.l a0,(a1)
- move.l a1,LN_PRED(a0)
- ;
- move.l (sp)+,a1 ; restore ptr
- ;
- ; Set error and return I/O
- ;
- 50$ move.b #IOERR_ABORTED,IO_ERROR(a1) ; set error code (2)
- move.b IO_FLAGS(a1),d1 ; get flags
- ori.b #1<<IOSERB_ABORT,d1 ; set abort flag
- andi.b #~(IOSERF_QUEUED|IOSERF_ACTIVE),d1 ; clear flags
- move.b d1,IO_FLAGS(a1) ; store flags
- btst #IOB_QUICK,d1 ; need to reply?
- bne.b 10$ ; nope, branch
- jsr _LVOReplyMsg(a6) ; send it back
- bra.b 10$ ; branch to return
- ;
- ; Abort all active/queued commands and reset internal state
- ;
- cnop 0,4 ; align for 020+
- cmd_Reset:
- move.l a1,-(sp) ; save I/O request
- bsr.b cmd_Flush ; go abort queued requests
- ;
- IFNE DANGER
- move.w #$04000,_intena
- addq.b #1,IDNestCnt(a6) ; disable interrupts
- ELSE
- jsr _LVODisable(a6) ; disable interrupts
- ENDC
- ;
- ; This must follow the DISABLE
- ;
- exg a5,a6 ; exchange base and ExecBase
- ;
- move.l cr_IOReq(pc),d0 ; active read?
- beq.b 10$ ; nope, branch
- movea.l d0,a1 ; get I/O request
- bsr dev_AbortIO ; go abort it
- ;
- ;
- ;
- 10$ move.l cw_IOReq(pc),d0 ; active write?
- beq.b 20$ ; nope, branch
- movea.l d0,a1 ; get I/O request
- bsr dev_AbortIO ; go abort it
- ;
- 20$ exg a5,a6 ; restore base and ExecBase
- move.l (sp)+,a1 ; restore I/O request
- moveq #8,d0 ; get char size
- move.b d0,IO_READLEN(a1) ; set read length
- move.b d0,IO_WRITELEN(a1) ; set write length
- moveq #1,d0 ; get stop bits
- move.b d0,IO_STOPBITS(a1) ; set stop bits
- move.l vb_DefBaud(a5),IO_BAUD(a1) ; set to default baud
- move.l vb_DefRBufLen(a5),IO_RBUFLEN(a1) ; set to default buflen
- bsr internalReset ; go set/verify parameters
- move.b d0,IO_ERROR(a1) ; set error code
- ;
- ; Set RC
- ;
- moveq #0,d0 ; I/O complete
- IFNE DANGER
- subq.b #1,IDNestCnt(a6)
- bge.b enable$
- move.w #$0C000,_intena
- enable$ rts
- ELSE
- jmp _LVOEnable(a6) ; enable interrupts
- ; return
- ENDC
- ;
- ; Abort all "queued" requests, leaving all active alone.
- ;
- cnop 0,4 ; align for 020+
- cmd_Flush:
- movem.l a1/a2,-(sp)
- ;
- ; Abort all queued read requests.
- ;
- lea readQ(pc),a2 ; get ptr to read queue
- bsr.b 20$ ; branch to abort
- ;
- ; Abort all queued write requests.
- ;
- lea writeQ(pc),a2 ; get ptr to write queue
- bsr.b 20$ ; branch to abort
- ;
- ; restore, and return to caller
- ;
- movem.l (sp)+,a1/a2
- ;
- ; Set RC and return
- ;
- moveq #0,d0 ; I/O complete
- ;
- ; !!!NOTE!!! In a mad attempt to save 2 bytes, this RTS is used
- ; by the subroutine below. Why waste 'em? B-)
- ;
- 10$ rts ; return ( used below too!! )
- ;
- ; Subroutine to remove and reply each I/O request.
- ;
- cnop 0,4 ; align for 020+
- IFNE DANGER
- 20$ move.l #custom+intena,a0
- move.w #$04000,(a0)
- addq.b #1,IDNestCnt(a6) ; disable interrupts
- ELSE
- 20$ jsr _LVODisable(a6) ; disable interrupts
- ENDC
- move.l a2,8(a2) ; clear list
- move.l (a2)+,a1 ; and get ptr to first I/O request
- move.l a2,-(a2) ;
- move.l a1,a2 ; save I/O request in a2
- ;
- IFNE DANGER
- subq.b #1,IDNestCnt(a6)
- bge.b enable$
- move.w #$0C000,(a0)
- enable$
- ELSE
- jsr _LVOEnable(a6) ; enable interrupts
- ENDC
- ;
- 25$ move.l (a2),d0 ; get next I/O request
- beq.b 10$ ; yep, branch to return
- ;
- move.l a2,a1 ; move I/O request to a1
- move.l d0,a2 ; save next I/O request in a2
- andi.b #~(1<<IOSERB_QUEUED),IO_FLAGS(a1) ; no longer queued
- moveq #IOERR_ABORTED,d0 ; indicate aborted
- move.b d0,IO_ERROR(a1) ; store status
- ;
- jsr _LVOReplyMsg(a6) ; send it back
- bra.b 25$ ; continue with next
- ;
- ; Process a CMD_READ request.
- ;
- cnop 0,4 ; align for 020+
- cmd_Read:
- ;
- ; Zero length requests just get returned.
- ;
- clr.l IO_ACTUAL(a1) ; clear bytes read
- move.l IO_LENGTH(a1),d0 ; get length and test
- beq.b 20$ ; yep, leave
- ;
- ; This can be used to circumvent a bug in NComm 3.0 which
- ; references the buffer even when there was nothing read.
- ;
- IFNE NCOMM
- move.l IO_DATA(A1),a0 ; get data pointer
- clr.b (a0) ; clear first byte in buffer
- ENDC
- ;
- ; The disable counter works just like exec's TDNestCnt field. It's
- ; initialized to -1. After incrementing, if it is 0, then we
- ; can attempt to process this request immediately. If it's > 0,
- ; then we're already disabled and we must queue this request.
- ;
- addq.l #1,disableRead ; incr disable count
- bgt.b 50$ ; >0, already disabled
- ;
- ; If we're already processing an request, this one has to wait
- ; until that one is done, so go queue it.
- ;
- tst.l cr_IOReq(pc) ; have an active request?
- bne.b 50$ ; yep, go queue this one
- ;
- ; If we don't have enough bytes to satisfy this request then go
- ; queue it.
- ;
- cmp.l i_InCnt(pc),d0 ; length > current bytes?
- bgt.b 50$ ; yep, go queue it
- ;
- ; Setup fields and go copy the data
- ;
- IFNE NCOMM
- move.l a0,cr_OutPtr ; get/set output ptr
- ELSE
- move.l IO_DATA(a1),cr_OutPtr ; get/set output ptr
- ENDC
- move.l d0,cr_Length ; get/set output count
- bsr copyData ; go copy 'em
- moveq #0,d0 ; I/O complete
- ;
- ; We're done, so back off the disable counter.
- ;
- 10$ subq.l #1,disableRead ; decr disable count
- ;
- ; Return to caller
- ;
- 20$ rts ; return
- ;
- ; Just set flags and queue. The read interrupt will handle it.
- ;
- 50$ ori.b #1<<IOSERB_QUEUED,IO_FLAGS(a1) ; indicate queued
- ;
- ; Add this request to the end.
- ;
- IFNE DANGER
- move.w #$04000,_intena
- addq.b #1,IDNestCnt(a6) ; disable interrupts
- ELSE
- jsr _LVODisable(a6) ; disable interrupts
- ENDC
- lea readQ(pc),a0 ; get pointer to read queue
- ; This is the ADDTAIL macro
- addq.l #LH_TAIL,a0
- move.l LN_PRED(a0),d0
- move.l a1,LN_PRED(a0)
- EXG d0,a0
- movem.l d0/a0,(a1)
- move.l a1,(a0)
- ;
- ;
- ; Indicate that this request was not handled immediatly.
- ;
- moveq #1,d0 ; I/O not complete
- IFNE DANGER
- subq.b #1,IDNestCnt(a6)
- bge.b 10$
- move.w #$0C000,_intena
- ELSE
- jsr _LVOEnable(a6) ; enable interrupts
- ENDC
- bra.b 10$ ; branch to return
- ;
- ; Process a CMD_WRITE request.
- ;
- cnop 0,4 ; align for 020+
- cmd_Write:
- clr.l IO_ACTUAL(a1) ; clear bytes written
- move.l IO_LENGTH(a1),d0 ; get length
- bne.b 10$ ; nope, proccess
- rts
- cnop 0,4 ; align for 020+
- 10$
- IFNE EOFCODE
- btst #SERB_EOFMODE,IO_SERFLAGS(a1) ; EOFMODE requested?
- beq.b 20$ ; nope, branch
- moveq #SerErr_InvParam,d0
- move.b d0,IO_ERROR(a1) ; Set error
- moveq #0,d0 ; I/O Complete
- rts
- cnop 0,4 ; align for 020+
- 20$
- ENDC
- IFNE NEGCHECK
- moveq #-1,d1 ; get value
- cmp.l d1,d0 ; length = -1?
- bne.b sdcmd_Break ; nope, skip scan
- ;
- ; Scan the data for null to calc the length
- ;
- move.l a0,d1 ; save data ptr
- 30$ tst.b (a0)+ ; does it equal 0? (first byte)
- beq.b 40$ ; yep, finish
- tst.b (a0)+ ; does it equal 0? (second byte)
- beq.b 40$ ; yep, finish
- tst.b (a0)+ ; does it equal 0? (third byte)
- beq.b 40$ ; yep, finish
- tst.b (a0)+ ; does it equal 0? (fourth byte)
- bne.b 30$ ; nope, loop
- 40$ move.l a0,d0
- sub.l d1,d0 ; calc # of bytes
- move.l d0,IO_LENGTH(a1) ; save length
- bra.b sdcmd_Break
- nop
- ENDC
- ;
- ; Entry point for Break command and fall through from cmd_Write.
- ;
- cnop 0,4 ; align for 020+
- sdcmd_Break:
- ;
- ; Just set flags and queue. The TBE interrupt will handle it.
- ;
- ori.b #1<<IOSERB_QUEUED,IO_FLAGS(a1) ; indicate queued
- ;
- ; Protect.
- ;
- IFNE DANGER
- move.w #$04000,_intena
- addq.b #1,IDNestCnt(a6) ; disable interrupts
- ELSE
- jsr _LVODisable(a6) ; disable interrupts
- ENDC
- ;
- ; Add request to end of queue.
- ;
- lea writeQ(pc),a0 ; get queue list ptr
- ; This is the ADDTAIL macro
- addq.l #LH_TAIL,a0
- move.l LN_PRED(a0),d0
- move.l a1,LN_PRED(a0)
- EXG d0,a0
- movem.l d0/a0,(a1)
- move.l a1,(a0)
- ;
- ; If we have an active request, don't force interrupt.
- ;
- tst.l cw_IOReq(pc) ; have an active request?
- bne.b 10$ ; yep, branch
- ;
- ; Force a TBE interrupt to get the writes going.
- ;
- move.w #INTF_SETCLR|INTF_TBE,_intreq ; make TBE pending
- ;
- ; Enable, set RC and return to caller.
- ;
- 10$ moveq #1,d0 ; I/O not complete
- IFNE DANGER
- subq.b #1,IDNestCnt(a6)
- bge.b enable$
- move.w #$0C000,_intena
- enable$ rts
- ELSE
- jmp _LVOEnable(a6) ; enable interrupts
- ; return
- ENDC
- ;
- ; Resets serial read buffer
- ;
- ; Since this routine is called internally, it must NOT reference
- ; the I/O request.
- ;
- cnop 0,4 ; align for 020+
- cmd_Clear:
- IFNE DANGER
- move.w #$04000,_intena
- addq.b #1,IDNestCnt(a6) ; disable interrupts
- ELSE
- jsr _LVODisable(a6) ; disable interrupts
- ENDC
- ;
- ; Load registers
- ;
- move.l vb_CurRBuf(a5),d0 ; get internal buffer ptr
- move.l vb_CurRBufLen(a5),d1 ; and internal buffer len
- lea i_BufPtr(pc),a0 ; get ptr internal control
- ;
- ; Initialize global buffer variables
- ;
- move.l d0,(a0)+ ; store buffer ptr
- move.l d0,(a0)+ ; set current input ptr
- move.l d0,(a0)+ ; set current output ptr
- add.l d1,d0 ; add buffer length
- move.l d0,(a0)+ ; store ptr to end of buffer
- clr.l (a0)+ ; clear byte cnt
- move.l vb_CurBaud(a5),d0 ; get internal baud
- lsr.l #4,d0 ; divide by 16
- sub.l d0,d1 ; subtract from length
- move.l d1,(a0) ; set threshold
- ;
- ; Enable, set RC and return.
- ;
- moveq #0,d0 ; I/O complete
- IFNE DANGER
- subq.b #1,IDNestCnt(a6)
- bge.b enable$
- move.w #$0C000,_intena
- enable$ rts
- ELSE
- jmp _LVOEnable(a6) ; enable interrupts
- ; return
- ENDC
- ;
- ;
- ;
- cnop 0,4 ; align for 020+
- cmd_Invalid
- move.b #IOERR_NOCMD,IO_ERROR(a1) ; set bad status
- moveq #0,d0 ; I/O complete
- rts ; return
- ;
- ; Returns number of bytes currently in internal buffer and
- ; current serial port status.
- ;
- ; NOTE: Not completely compatible with standard serial.device
- ; since it doesn't return the upper byte of IO_STATUS.
- ;
- cnop 0,4 ; align for 020+
- sdcmd_Query:
- IFNE DANGER
- move.l #custom+intena,a0
- move.w #$04000,(a0)
- addq.b #1,IDNestCnt(a6) ; disable interrupts
- ELSE
- jsr _LVODisable(a6) ; disable interrupts
- ENDC
- moveq #0,d0 ; clear d0
- move.b _ciabpra,d0 ; get PR register
- andi.b #~PRTMASK,d0 ; zap printer bits
- ;
- ; To use this Set SETDSR to one. This was done
- ; for a user whose DSR pin did not function.
- ;
- IFNE SETDSR
- andi.b #~(1<<CIAB_COMDSR),d0 ; set DSR
- ENDC
- ;
- ;
- ;
- move.w d0,IO_STATUS(a1) ; store status
- move.l i_InCnt(pc),IO_ACTUAL(a1) ; byte left in buffer
- ;
- ; Enable, set RC and return.
- ;
- moveq #0,d0 ; I/O complete
- IFNE DANGER
- subq.b #1,IDNestCnt(a6)
- bge.b enable$
- move.w #$0C000,(a0)
- enable$ rts
- ELSE
- jmp _LVOEnable(a6) ; enable interrupts
- ; return
- ENDC
- ;
- ;
- ;
- cnop 0,4 ; align for 020+
- sdcmd_SetParams:
- ;
- ; Validate the read, write, and stop bit lengths.
- ;
- moveq #8,d0 ; get char length
- cmp.b IO_READLEN(a1),d0 ; 8 bit chars for read?
- bne.b 40$ ; nope, branch
- cmp.b IO_WRITELEN(a1),d0 ; 8 bit chars for write?
- bne.b 40$ ; nope, branch
- moveq #1,d0 ; get stop bits
- cmp.b IO_STOPBITS(a1),d0 ; 1 stop bit?
- bne.b 40$ ; nope, branch
- ;
- ; Get and validate the baud rate.
- ;
- move.l IO_BAUD(a1),d1 ; get baud from I/O req
- bne.b 20$ ; specified?
- move.l vb_CurBaud(a5),d1 ; get current baud from base
- bne.b 20$ ; specified?
- move.l vb_DefBaud(a5),d1 ; get default baud from base
- 20$ cmp.l #110,d1 ; too low?
- blt.b 40$ ; error
- cmp.l #292000,d1 ; too high?
- bgt.b 40$ ; error
- ;
- ; Get and validate the buffer length.
- ;
- move.l IO_RBUFLEN(a1),d0 ; get buffer length
- bne.b 30$ ; specified?
- move.l vb_CurRBufLen(a5),d0 ; get current from base
- bne.b 30$ ; specified?
- move.l vb_DefRBufLen(a5),d0 ; get default from base
- ;
- 30$ bsr.b internalReset ; go init baud and buffer
- 35$ move.b d0,IO_ERROR(a1) ; set error code
- bne.b 39$
- ;
- ; If the 7wire bit is not on, we will only use 3-wire protocol
- ;
- moveq #0,d0 ; clear flag
- btst #SERB_7WIRE,IO_SERFLAGS(a1) ; use 7wire handshaking?
- beq.b 36$ ; nope, branch
- moveq #1,d0 ; set flag
- 36$ move.l d0,Handshake ; store flag
- ;
- ; Set RC and return.
- ;
- 39$ moveq #0,d0 ; I/O complete
- rts ; return
- ;
- ; Invalid parm detected.
- ;
- 40$ moveq #SerErr_InvParam,d0 ; set error
- bra.b 35$ ; go return
- ;
- ; The NewStyleDevices Query command.
- ;
- cnop 0,4 ; align for 020+
- nscmd_DeviceQuery:
- move.l IO_DATA(a1),d0
- beq.b 10$
- move.l d0,a0
- moveq #NSDEVICEQUERYRESULT_SIZE,d0
- move.l d0,SIZEAVAILABLE(a0)
- move.l d0,IO_ACTUAL(a1)
- move.w #NSDEVTYPE_SERIAL,DEVICETYPE(a0)
- move.l a1,-(sp)
- lea cmdlist(pc),a1
- move.l a1,SUPPORTEDCOMMANDS(a0)
- move.l (sp)+,a1
- 10$ moveq #0,d0
- rts
- ;
- ; Reset the buffer and baud rate
- ;
- ; Registers: D0 = Buffer length
- ; D1 = Baud rate
- ;
- cnop 0,4 ; align for 020+
- internalReset:
- ;
- ; Disable interrupts.
- ;
- IFNE DANGER
- move.w #$04000,_intena
- addq.b #1,IDNestCnt(a6) ; disable interrupts
- ELSE
- jsr _LVODisable(a6) ; disable interrupts
- ENDC
- ;
- ; Save buffer length and go set serper.
- ;
- move.l d0,-(sp) ; save D0
- move.l d1,d0 ; get baud rate
- ;
- ; Set serial period register
- ;
- cmp.l vb_CurBaud(a5),d0 ; current baud = new baud?
- beq.b 40$ ; yep, just exit
- move.l d0,vb_CurBaud(a5) ; save new baud
- move.l d0,d1 ; save again
- lsl.l #3,d0 ; baud *= 8
- sub.l d1,d0 ; baud -= saved baud
- move.l #25000000,d1 ; get NTSC base
- cmpi.b #50,PowerSupplyFrequency(a6) ; PAL machine?
- bne.b 5$ ; nope, branch
- move.l #24772416,d1 ; get PAL base
- 5$ cmp.l #$FFFF,d0 ; Divide
- ble.b 20$ ;
- lsr.l #5,d0 ;
- IFNE NEWCODE
- divu.l d0,d1 ;
- ELSE
- divu.w d0,d1 ;
- andi.l #$FFFF,d1 ;
- ENDC
- lsr.l #5,d1 ;
- bra.b 30$ ;
- cnop 0,4 ; align for 020+
- 20$ divu.w d0,d1 ;
- 30$ move.w d1,_serper ; set period value
- 40$
- move.l (sp)+,d0 ; restore D0
- ;
- ; Determine if the buffer length is adequate for the selected CPS.
- ; If not, use 64K for the length.
- ;
- move.l vb_CurBaud(a5),d1 ; get current baud
- lsr.l #2,d1 ; divide by 4
- cmp.l d1,d0 ; buflen > CPS
- bhi.b 10$ ; yep, branch
- move.l #65536,d0 ; else use 64K
- ;
- ; Allocate new internal buffer
- ;
- 10$ cmp.l vb_CurRBufLen(a5),d0 ; len same as previous?
- beq.b 11$ ; yep, so no need to alloc
- move.l d0,d1 ; save length
- movem.l d1/a1,-(sp)
- moveq #MEMF_PUBLIC|MEMF_FAST,d1 ; public memory
- jsr _LVOAllocMem(a6) ; go allocate it
- movem.l (sp)+,d1/a1
- tst.l d0 ; did we get it?
- beq.b 21$ ; if zero, error
- move.l d0,-(sp) ; save d0
- bsr.b freeBuf ; go free previous buffer
- move.l (sp)+,vb_CurRBuf(a5) ; store new ptr
- move.l d1,vb_CurRBufLen(a5) ; and length
- bsr cmd_Clear ; go setup buffer
- 11$ moveq #0,d0 ; success
- bra.b 22$ ; return
- cnop 0,4 ; align for 020+
- 21$ moveq #SerErr_BufErr,d0 ; set error status
- 22$
- ;
- ; Enable and return to caller.
- ;
- IFNE DANGER
- subq.b #1,IDNestCnt(a6)
- bge.b enable$
- move.w #$0C000,_intena
- enable$ rts
- ELSE
- jmp _LVOEnable(a6) ; enable interrupts / return (D0 has status)
- ENDC
- ;
- ; Free internal buffer
- ;
- cnop 0,4 ; align for 020+
- freeBuf:
- move.l vb_CurRBuf(a5),d0 ; is one there?
- beq.b 10$ ; no so branch
- movem.l d1/a1,-(sp) ; save registers
- movea.l d0,a1 ; get ptr
- move.l vb_CurRBufLen(a5),d0 ; get length
- clr.l vb_CurRBuf(a5) ; clear
- clr.l vb_CurRBufLen(a5) ; clear
- jsr _LVOFreeMem(a6) ; free it
- movem.l (sp)+,d1/a1
- 10$ rts ; return
- ;
- ; Checks CTS status and if clear generates a TBE interrupt or
- ; requeues the timer request.
- ;
- ; Entered from Exec using the MsgPort callback.
- ;
- ; Input: a6 = ExecBase
- ; Output: none
- ;
- ; No need to preserve d0/d1/a0/a1
- ;
- cnop 0,4 ; align for 020+
- timerRtn:
- lea timerReq(pc),a1 ; get ptr to timer request
- ; This is the REMOVE macro
- move.l (a1)+,a0
- move.l (a1),a1 ; LN_PRED
- move.l a0,(a1)
- move.l a1,LN_PRED(a0)
- ;
- ; If we were breaking, reset adkcon.
- ;
- move.l #custom+adkconr,a0 ; get ptr to custom regs
- btst #ADKB_UARTBRK&7,(a0) ; were we breaking?
- beq.b 10$ ; nope, skip reset
- ;
- move.w #ADKF_UARTBRK,adkcon-adkconr(a0) ; stop breaking
- ;
- ;
- ;
- 10$ tst.l Handshake(pc) ; are we handshaking?
- beq.b 20$ ; nope, generate interrupt
- btst #CIAB_COMCTS,_ciabpra ; clear to send?
- beq.b 20$ ; yep, go start writing
- ;
- lea timerReq(pc),a1 ; get ptr to timer request
- move.l #1000,IOTV_TIME+TV_MICRO(a1) ; wait for .001 seconds
- jmp _LVOSendIO(a6) ; go queue it / return
- ;
- ; CTS is clear so generate TBE interrupt to restart writing
- ;
- cnop 0,4 ; align for 020+
- 20$ move.w #INTF_SETCLR|INTF_TBE,intreq-adkconr(a0) ; set TBE interrupt
- rts ; return
- ;
- ; Non serial interrupt
- ; Handles:
- ; INTB_DSKBLK
- ; INTB_SOFTINT
- ;
- ; a0 - custom chips base
- ; a1 - is_Data
- ;
- cnop 0,4 ; align for 020+
- level1n:
- movem.l d1/a1/a5/a6,-(sp) ; save registers
- move.l d0,d1 ; get enabled interrupts
- swap d1
- move.l SysBase(pc),a6 ; get ExecBase
- and.l d0,d1 ; and in requested interrupts
- ;
- btst #INTB_DSKBLK,d1 ; Disk block done?
- beq.b 10$ ; nope, branch
- ;
- movem.l IVDSKBLK(a6),a1/a5 ; get data and code ptrs
- pea 20$(pc) ; push return address
- jmp (a5) ; jump to routine
- ;
- 10$
- ;
- movem.l IVSOFTINT(a6),a1/a5 ; get data and code ptrs
- jsr (a5) ; jump to routine
- ;
- 20$
- movem.l (sp)+,d1/a1/a5/a6 ; restore registers
- movem.l (sp)+,d0/a0
- rte ; return
- ;
- ; Level 1 interrupt handler
- ; Handles:
- ; INTB_TBE
- ;
- ; a1 - is_Data
- ;
- cnop 0,4 ; align for 020+
- level1:
- movem.l d0/a0,-(sp)
- move.l #custom,a0 ; get ptr to custom regs
- move.l intenar(a0),d0 ; get intenar & intreqr
- btst #INTB_INTEN+16,d0 ; interrupts enabled?
- beq.b 30$ ; nope, ignore
- btst #INTB_TBE,d0 ; xmit buffer empty?
- beq.b level1n ; nope, invoke old handler
- ;
- ; Handle "Transmit Buffer Empty" interrupt (write)
- ;
- move.w #INTF_TBE,intreq(a0) ; clear interrupt
- ;
- ; If we're not handshaking, bypass it.
- ;
- 10$ tst.l Handshake(pc) ; are we handshaking?
- beq.b 20$ ; nope, skip CTS test
- btst #CIAB_COMCTS,_ciabpra ; clear to send?
- bne.b 40$ ; nope, branch
- ;
- ; If cw_Length goes negative here, we are either done with a
- ; request or we were called as a result of a fake interrupt
- ; to force us to get the next request going.
- ;
- 20$ subq.l #1,cw_Length ; decr write length
- blt.b 60$ ; < zero, done, branch
- ;
- ; Currently processing a request.
- ;
- movea.l cw_Buffer(pc),a0 ; get buffer ptr
- move.w #256,d0 ; set stop bit
- move.b (a0)+,d0 ; get next byte
- move.l a0,cw_Buffer ; store buffer ptr
- move.w d0,_serdat ; store in serdat reg
- ;
- 30$ movem.l (sp)+,d0/a0
- rte ; return
- ;
- ; Queue a timer request to recheck CTS status
- ;
- cnop 0,4 ; align for 020+
- 40$
- movem.l d1/a1/a6,-(sp)
- lea timerReq(pc),a1 ; get ptr to timer request
- move.l #1000,IOTV_TIME+TV_MICRO(a1) ; wait for .001 seconds
- movea.l SysBase(pc),a6 ; get ExecBase
- jsr _LVOSendIO(a6) ; queue the request
- movem.l (sp)+,d1/a1/a6
- bra.b 30$ ; go return
- ;
- ; There aren't anymore requests, so clear and exit
- ;
- cnop 0,4 ; align for 020+
- 50$ clr.l cw_Length-Start(a6) ; clear length
- clr.l cw_IOReq-Start(a6) ; clear
- movem.l (sp)+,d1/a1/a6
- bra.b 30$ ; go return
- ;
- ; Write request completed
- ;
- cnop 0,4 ; align for 020+
- 60$ movem.l d1/a1/a6,-(sp) ; save registers
- ;
- move.l cw_IOReq(pc),d0 ; active I/O request?
- beq.b 70$ ; nope, branch
- ;
- ; Reply it and setup for next
- ;
- movea.l d0,a1 ; get I/O request
- andi.b #~(1<<IOSERB_ACTIVE),IO_FLAGS(a1) ; no longer active
- clr.b IO_ERROR(a1) ; no error
- movea.l SysBase(pc),a6 ; get ExecBase
- jsr _LVOReplyMsg(a6) ; return I/O request
- ;
- 70$ lea Start(pc),a6 ; get section base
- ;
- lea writeQ(pc),a1 ; get ptr to write queue
- move.l (a1),a0 ; get head of list
- move.l (a0),d0 ; get successor
- beq.b 50$ ; end of list? yep, branch
- ;
- ; Remove the node from the list
- ;
- move.l d0,(a1) ; make new head
- exg.l d0,a0 ; swap nodes
- move.l a1,LN_PRED(a0) ; store predecessor
- ;
- move.l d0,a1 ; get I/O request
- ;
- ; If it's a BREAK, then branch to process as such.
- ;
- cmpi.w #SDCMD_BREAK,IO_COMMAND(a1) ; BREAK command?
- beq.b 100$ ; yep, branch
- ;
- ; Check for absolute length
- ;
- move.l IO_DATA(a1),a0 ; get data ptr
- move.l IO_LENGTH(a1),d0 ; get length
- ;
- 90$ move.l d0,IO_ACTUAL(a1) ; go ahead and set it
- move.b IO_FLAGS(a1),d1
- move.l d0,cw_Length-Start(a6) ; store length
- andi.b #~(1<<IOSERB_QUEUED),d1 ; no longer queued
- move.l a0,cw_Buffer-Start(a6) ; store buffer ptr
- ori.b #1<<IOSERB_ACTIVE,d1 ; make it active
- move.l a1,cw_IOReq-Start(a6) ; store I/O request ptr
- move.b d1,IO_FLAGS(a1)
- ;
- movem.l (sp)+,d1/a1/a6
- bra 10$ ; go start request
- ;
- ; Start the BREAK.
- ;
- cnop 0,4 ; align for 020+
- 100$ move.b IO_FLAGS(a1),d1
- clr.l cw_Length-Start(a6) ; clear length
- andi.b #~(1<<IOSERB_QUEUED),d1 ; no longer queued
- move.l a1,cw_IOReq-Start(a6) ; store I/O request ptr
- ori.b #1<<IOSERB_ACTIVE,d1 ; make it active
- move.w #ADKF_SETCLR|ADKF_UARTBRK,_adkcon ; start break
- move.b d1,IO_FLAGS(a1)
- move.l IO_BRKTIME(a1),d0 ; get break time
- lea timerReq(pc),a1 ; get ptr to timer request
- move.l d0,IOTV_TIME+TV_MICRO(a1) ; set the timeout
- movea.l SysBase(pc),a6 ; get ExecBase
- jsr _LVOSendIO(a6) ; queue the request
- movem.l (sp)+,d1/a1/a6
- bra 30$ ; go exit
- ;
- ; Non serial interrupt
- ; Handles:
- ; INTB_DSKSYNC
- ;
- ; a0 - custom chips base
- ;
- cnop 0,4 ; align for 020+
- level5n:
- movem.l d1/a1/a5/a6,-(sp) ; save registers
- move.l d0,d1
- move.l SysBase(pc),a6 ; get ExecBase
- swap d1
- movem.l IVDSKSYNC(A6),a1/a5 ; get data and code ptrs
- and.l d0,d1
- move.l #custom,a0 ; get ptr to custom regs
- jsr (a5) ; branch to routine
- movem.l (sp)+,d1/a1/a5/a6 ; restore registers
- movem.l (sp)+,d0/a0
- rte ; return
- ;
- ; Default Level 5 handler
- ; Handles:
- ; INTB_RBF
- ;
- ; a1 - custom chips base
- ;
- cnop 0,4 ; align for 020+
- level5:
- movem.l d0/a0,-(sp)
- move.l #custom+serdatr,a0 ; get ptr to custom regs
- ;
- move.l intenar-serdatr(a0),d0 ; get intenar & intreq
- btst #INTB_INTEN+16,d0 ; interrupts enabled?
- beq.b 41$ ; nope, ignore
- btst #INTB_RBF,d0 ; receive buffer full?
- beq.b level5n ; nope, invoke old handler
- ;
- 10$ move.w (a0),d0 ; Overrun?
- bpl.b 20$ ; nope, branch
- ;
- ; We've missed some data, so set overrun flag.
- ;
- addq.l #1,Overrun ; set overrun flag
- 20$ move.w #INTF_RBF,intreq-serdatr(a0) ; clear RBF interrupt
- move.l i_BufIn(pc),a0 ; get current ptr
- move.b d0,(a0)+ ; store received byte
- addq.l #1,i_InCnt ; incr bytes in buffer
- ;
- cmpa.l i_BufEnd(pc),a0 ; hit end of buffer?
- bne.b 30$ ; nope, branch
- ;
- ; Hit physical end of buffer, so wrap to the start of the buffer.
- ;
- movea.l i_BufPtr(pc),a0 ; get buffer ptr
- 30$ move.l a0,i_BufIn ; store input ptr
- ;
- subq.l #1,i_Thresh ; close to full buffer?
- bne.b 40$ ; nope, branch
- ;
- ; Hit buffer threshold, so tell other end not to send any more
- ; data.
- ;
- tst.l Handshake(pc) ; are we handshaking?
- beq.b 40$ ; nope, skip RTS
- ori.b #1<<CIAB_COMRTS,_ciabpra ; block further input
- ;
- 40$
- IFEQ NEWCODE
- move.l #custom+serdatr,a0 ; get ptr to custom regs
- btst #INTB_RBF&7,intreqr-serdatr(a0) ; receive buffer full?
- bne.b 10$ ; yep, go get another byte
- ENDC
- ;
- 41$ movem.l (sp)+,d0/a0
- rte ; return
- ;
- ;
- ; a1 - IS_DATA
- ; a5 - jump vector register
- ;
- cnop 0,4 ; align for 020+
- level2:
- ;
- ; If there's nothing in the buffer, there's no point in going
- ; any further.
- ;
- tst.l i_InCnt(pc) ; anything in the buffer?
- beq.b 9$ ; nope, branch
- ;
- ; If we've been "disabled" then get out.
- ;
- 20$ tst.l disableRead(pc) ; internally disabled?
- bge.b 10$ ; yep, get out of here
- lea Start(pc),a5 ; get base
- ;
- ; If we have an active request, branch down and try to fulfill it.
- ;
- move.l cr_IOReq(pc),d0 ; get and test active I/O
- bne.b 30$ ; nzero, active, branch
- ;
- ; Get first node in list and test if empty.
- ;
- move.l (a1),a0 ; get head of list
- move.l (a0),d0 ; get successor
- beq.b 9$ ; end of list? yep, branch
- ;
- ; Remove the node from the list
- ;
- move.l d0,(a1) ; make new head
- exg.l d0,a0 ; swap nodes
- move.l a1,LN_PRED(a0) ; store predecessor
- ;
- ; Setup fields for processing a read request
- ;
- movea.l d0,a1 ; get I/O request
- move.b IO_FLAGS(a1),d1
- andi.b #~(1<<IOSERB_QUEUED),d1 ; no longer queued
- move.l a1,cr_IOReq-Start(a5) ; store I/O request
- ori.b #1<<IOSERB_ACTIVE,d1 ; make it active
- move.l IO_DATA(a1),cr_OutPtr-Start(a5) ; get/set output ptr
- move.b d1,IO_FLAGS(a1)
- move.l IO_LENGTH(a1),cr_Length-Start(a5) ; get/set output count
- ;
- ; Process an active I/O request
- ;
- 30$ movea.l SysBase(pc),a6 ; get ExecBase
- move.l d0,a1 ; get I/O request
- bsr.b copyData ; go copy 'em
- tst.l d0 ; done with request?
- beq.b 9$ ; nope, branch
- ;
- ; the request has been satisfied, so return it.
- ;
- clr.l cr_IOReq-Start(a5) ; clear request
- andi.b #~(1<<IOSERB_ACTIVE),IO_FLAGS(a1) ; no longer active
- jsr _LVOReplyMsg(a6) ; return I/O
- 10$ moveq #0,d0 ; set Z flag
- 9$ rts ; return
- ;
- ; Registers:
- ; Entry: A1 Ptr to I/O Request
- ; A6 ExecBase
- ; Exit: D0 ZERO - request not done, do not reply it
- ; NZERO - request done, reply it
- ;
- cnop 0,4 ; align for 020+
- copyData:
- ;
- ; Process an active I/O request (or fall through from above)
- ;
- movem.l d2-d5/a1-a5,-(sp) ; save registers
- lea Start(pc),a5 ; get base
- movea.l a1,a4 ; get I/O request
- ;
- movea.l i_BufOut(pc),a2 ; get current bufout ptr
- movea.l cr_OutPtr(pc),a3 ; get current output ptr
- move.l cr_Length(pc),d2 ; get current bytes needed
- move.l i_InCnt(pc),d3 ; get current bytes in buffer
- ;
- ; If we don't have enough bytes to satisfy the request,
- ; set the length to the number of bytes we do have.
- ;
- cmp.l d2,d3 ; enuf to satisfy request?
- bge.b 15$ ; yep, so branch
- move.l d3,d2 ; # to copy = # in buffer
- bra.b 16$ ; branch to loop entry
- ;
- ; Start of copy loop.
- ;
- cnop 0,4 ; align for 020+
- 10$ movea.l i_BufPtr(pc),a2 ; reset bufout to start
- ;
- ; Entry point of copy loop.
- ;
- 15$ move.l d2,d3 ; xfer # of bytes to copy
- 16$
- ;
- ; If the copy will extend past the end of the buffer, we can
- ; only copy the number of bytes to the end this go around.
- ;
- move.l i_BufEnd(pc),d0 ; get ptr to end of buf
- sub.l a2,d0 ; calc # of bytes to end
- cmp.l d0,d3 ; # to copy < # to end?
- blt.b 20$ ; yep, branch
- move.l d0,d3 ; get bytes to end
- ;
- ; Registers:
- ;
- ; A2 = pointer from which data will be copied
- ; A3 = pointer to which data will be copied
- ; D2 = number of bytes that need to be copied
- ; D3 = number of bytes to copy this iteration
- ;
- 20$ move.l d3,d0 ; get length
- IFNE EOFCODE
- btst #SERB_EOFMODE,IO_SERFLAGS(a4) ; EOFMODE requested?
- beq.b 30$ ; nope, just go copy
- ;
- ; EOFMODE was specified so copy characters 1 at a time until
- ; we hit an EOF character, the output butter has filled, or
- ; the input buffer has drained.
- ;
- movem.l IO_TERMARRAY(a4),d4/d5 ; get termarry
- rol.l #8,d4
- move.l d4,a1
- rol.l #8,d5
- ;
- 21$ move.b (a2)+,d1 ; get byte
- ; This way the term char IS copied (if term char is not copied eofmode will fail)
- move.b d1,(a3)+ ; put in output buffer
- ;
- cmp.b d4,d1 ; found term char?
- bge.b 22$ ; possibly, branch (taken 0, not taken 1)
- rol.l #8,d4
- cmp.b d4,d1 ; found term char?
- bge.b 22$ ; possibly, branch
- rol.l #8,d4
- cmp.b d4,d1 ; found term char?
- bge.b 22$ ; possibly, branch
- rol.l #8,d4
- cmp.b d4,d1 ; found term char?
- bge.b 22$ ; possibly, branch
- move.l d5,d4
- cmp.b d4,d1 ; found term char?
- bge.b 22$ ; possibly, branch
- rol.l #8,d4
- cmp.b d4,d1 ; found term char?
- bge.b 22$ ; possibly, branch
- rol.l #8,d4
- cmp.b d4,d1 ; found term char?
- bge.b 22$ ; possibly, branch
- rol.l #8,d4
- cmp.b d4,d1 ; found term char?
- 22$ beq.b 24$ ; term char found?
- ;
- ; Didn't find a term character, so continue with the copy loop
- ;
- 23$ move.l a1,d4
- subq.l #1,d0 ; decr length counter
- bne.b 21$ ; continue if more
- bra.b 40$ ; done with copy, branch
- ;
- ; We've found a termination character.
- ;
- cnop 0,4 ; align for 020+
- 24$ clr.l cr_Length-Start(a5) ; done with request
- bra.b 50$ ; branch
- cnop 0,4 ; align for 020+
- ENDC
- ;
- ; EOFMODE not specified, so just do a bulk copy.
- ;
- ; XXX POSSIBLE SPEEDUP XXX
- ;
- ; For short copies it would be quicker to have a simple inline
- ; loop, but what's short??? It would be different by CPU.
- ;
- 30$ movea.l a3,a1 ; where to put it
- movea.l a2,a0 ; where to get it
- ; NB: buffer size is multiple of 64bytes (not contents size)
- ; most copys are 1 or 2 bytes, max copy usually seen is 256 bytes
- jsr _LVOCopyMem(a6) ; we use copymemquicker patch by *Art
- adda.l d3,a2 ; update bufout
- adda.l d3,a3 ; update outptr
- ;
- ; Fall through and entered from EOFMODE loop
- ;
- ; If the following calculation results in a value greater than
- ; zero, then we have a buffer wrap and need to process the
- ; remaining bytes at the beginning of the buffer.
- ;
- 40$ sub.l d3,d2 ; calc bytes left to copy
- bgt.b 10$ ; >0, more to copy, branch
- ;
- ;
- ;
- 50$ move.l a3,d1 ; get outptr
- sub.l cr_OutPtr(pc),d1 ; calc length
- move.l a3,cr_OutPtr-Start(a5) ; update outptr
- ;
- ; Update output ptr and I/O request
- ;
- move.l a2,i_BufOut-Start(a5) ; store bufout ptr
- add.l d1,IO_ACTUAL(a4) ; update I/O request
- ;
- ; Update number of bytes left in the buffer.
- ;
- sub.l d1,i_InCnt-Start(a5) ; calc bytes left in buffer
- ;
- ; If the threshold becomes positive here, then, if requested,
- ; tell the other end that it's okay to start sending more data.
- ;
- add.l d1,i_Thresh-Start(a5) ; calc thresh and test
- ble.b 60$ ; <= 0, need more data, skip
- tst.l Handshake(pc) ; are we handshaking?
- beq.b 60$ ; nope, skip RTS
- andi.b #~(1<<CIAB_COMRTS),_ciabpra ; ready to recieve more data
- ;
- ; Set error if we've had any overruns.
- ;
- 60$ tst.l Overrun(pc) ; did overrun occur?
- beq.b 70$ ; nope, branch
- clr.l Overrun-Start(a5) ; reset overrun flag
- move.b #SerErr_LineErr,IO_ERROR(a4) ; set error code
- ;
- ; Calc number of bytes left to copy. If the result is greater
- ; than zero, then we have more to copy so return an incomplete
- ; status.
- ;
- 70$ moveq #0,d0 ; assume I/O incomplete
- sub.l d1,cr_Length-Start(a5) ; update length and test
- bgt.b 90$ ; >0, more to do, branch
- ;
- ; We've completed the I/O request either by copying the requested
- ; of bytes or by finding an EOFMODE character, so return a "reply"
- ; status.
- ;
- moveq #1,d0 ; indicate reply
- ;
- ; Restore and exit
- ;
- 90$
- movem.l (sp)+,d2-d5/a1-a5
- rts ; return (status in D0)
- ;
- ; Align data
- ;
- CNOP 0,4
- ;
- ;
- ;
- Init:
- DC.L sizeof_Base8n1
- DC.L funcTab
- DC.L dataTab
- DC.L InitRoutine
- ;
- ;
- ;
- funcTab:
- DC.W -1
- DC.W dev_Open-funcTab
- DC.W dev_Close-funcTab
- DC.W dev_Expunge-funcTab
- DC.W dev_Null-funcTab
- DC.W dev_BeginIO-funcTab
- DC.W dev_AbortIO-funcTab
- DC.W -1
- ;
- ;
- ;
- dataTab:
- INITBYTE LN_TYPE,NT_DEVICE
- INITLONG LN_NAME,Name
- INITBYTE LIB_FLAGS,LIBF_SUMUSED|LIBF_CHANGED
- INITWORD LIB_VERSION,VERSION
- INITWORD LIB_REVISION,REVISION
- INITLONG LIB_IDSTRING,IdString
- DC.W 0
- ;
- ; String Constants
- ;
- miscresource:
- DC.B "misc.resource",0
- timerdevice:
- DC.B "timer.device",0
- intuitlib:
- DC.B "intuition.library",0
- Name:
- DC.B "8n1.device",0
- IdString:
- VSTRING
- ;
- ; End of checksummed area. (Realigns data too!)
- ;
- ENDTag:
- CNOP 0,4
- ;
- ; Global SysBase (Use instead of _AbsExecBase for speed)
- ;
- SysBase:
- DC.L 0
- ;
- ; Internal buffer tracking (DO NOT CHANGE THE ORDER!!!!)
- ;
- i_BufPtr:
- DC.L 0
- i_BufIn:
- DC.L 0
- i_BufOut:
- DC.L 0
- i_BufEnd:
- DC.L 0
- i_InCnt:
- DC.L 0
- i_Thresh:
- DC.L 0
- ;
- ; Used while processing a read request.
- ;
- cr_IOReq:
- DC.L 0
- cr_OutPtr:
- DC.L 0
- cr_Length:
- DC.L 0
- ;
- ; List head for read requests
- ;
- readQ:
- DC.L readQ+MLH_TAIL
- DC.L 0
- DC.L readQ
- ;
- ; Write control.
- ;
- cw_Length:
- DC.L 0
- cw_Buffer:
- DC.L 0
- cw_IOReq:
- DC.L 0
- ;
- ; List head for write requests
- ;
- writeQ:
- DC.L writeQ+MLH_TAIL
- DC.L 0
- DC.L writeQ
- ;
- ;
- ;
- timerPort:
- DC.L 0 ; LN_SUCC
- DC.L 0 ; LN_PRED
- DC.B NT_MSGPORT ; LN_TYPE
- DC.B 0 ; LN_PRI
- DC.L 0 ; LN_NAME
- DC.B 3 ; MP_FLAGS (undoc'ed)
- DC.B 0 ; MP_SIGBIT
- DC.L timerRtn ; MP_SIGTASK
- DC.L timerPort+MP_MSGLIST+LH_TAIL ; LH_HEAD
- DC.L 0 ; LH_TAIL
- DC.L timerPort+MP_MSGLIST ; LH_TAILPRED
- DC.B 0 ; LH_TYPE
- DC.B 0 ; LH_pad
- DC.W 0 ; long align
- ;
- ;
- ;
- timerReq:
- DC.L 0 ; LN_SUCC
- DC.L 0 ; LN_PRED
- DC.B NT_MESSAGE ; LN_TYPE
- DC.B 0 ; LN_PRI
- DC.L 0 ; LN_NAME
- DC.L timerPort ; MN_REPLYPORT
- DC.W IOTV_SIZE ; MN_LENGTH
- DC.L 0 ; IO_DEVICE
- DC.L 0 ; IO_UNIT
- DC.W TR_ADDREQUEST ; IO_COMMAND
- DC.B 0 ; IO_FLAGS
- DC.B 0 ; IO_ERROR
- DC.L 0 ; TV_SECS
- DC.L 0 ; TV_MICROS
- ;
- ;
- ;
- VBInterrupt:
- DC.L 0 ; LN_SUCC
- DC.L 0 ; LN_PRED
- DC.B NT_INTERRUPT ; LN_TYPE
- DC.B 0 ; LN_PRI
- DC.L Name ; LN_NAME
- DC.L readQ ; IS_DATA
- DC.L level2 ; IS_CODE
- ;
- ; Global flags
- ;
- CNOP 0,4
- Overrun:
- DC.L 0
- Handshake:
- DC.L 1
- disableRead:
- DC.L -1
- cmdlist:
- dc.w CMD_RESET
- dc.w CMD_READ
- dc.w CMD_WRITE
- dc.w CMD_CLEAR
- dc.w CMD_FLUSH
- dc.w SDCMD_QUERY
- dc.w SDCMD_BREAK
- dc.w SDCMD_SETPARAMS
- dc.w NSCMD_DEVICEQUERY
- dc.w 0
- ;
- ;
- ;
- END
-
-